package test.ssl;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

public class ShowPeerCert
{
	public static final String SERVER_ADDR = "mail.google.com";
	public static final int SERVER_PORT = 443;
	public static final String HTTPS_REQUEST = "GET / HTTP/1.0\r\n\r\n";

	public static void main(String[] args)
		throws KeyStoreException, NoSuchAlgorithmException,
			CertificateException, IOException,
			UnrecoverableKeyException, KeyManagementException
	{
		//	使用IPv4，而不是IPv6
        System.setProperty("java.net.preferIPv4Stack", "true");
        System.setProperty("java.net.preferIPv6Addresses", "false");

		//	构建证书文件流
		String path = ShowPeerCert.class.getResource("").getPath() + "Client.jks.pk";
		InputStream fis = new FileInputStream(path);

		//	构建证书存储信息对象
		KeyStore ks = KeyStore.getInstance("JKS");
		ks.load(fis, "654321".toCharArray());

		//	构建证书管理器工厂对象
		KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
		kmf.init(ks, "654321".toCharArray());

		//	构建SSL上下文
		SSLContext ctx = null;
		{
			NoSuchAlgorithmException exception = null;
			try {ctx = SSLContext.getInstance("TLS");}catch (NoSuchAlgorithmException e){};
			if(ctx == null)
				try {ctx = SSLContext.getInstance("SSLv2");}catch (NoSuchAlgorithmException e){};
			if(ctx == null)
				try {ctx = SSLContext.getInstance("SSL");}catch (NoSuchAlgorithmException e){exception = e;};
			if(ctx == null)
				throw exception;
		}
		ctx.init(kmf.getKeyManagers(), new TrustManager[]{new CertTrustManager()}, null);

		//	构建SSL套接字工厂并创建连接
		SSLSocketFactory sf = ctx.getSocketFactory();
		Socket socket = sf.createSocket(SERVER_ADDR, SERVER_PORT);

		//	与服务端通信
		OutputStream os = socket.getOutputStream();
		os.write(HTTPS_REQUEST.getBytes("UTF-8"));
		os.flush();
		InputStream is = socket.getInputStream();
		int len = is.available();
		byte[] buffer = new byte[len];
		is.read(buffer);
		String httpResponse = new String(buffer, "UTF-8");
		System.out.println(httpResponse);

		//	关闭网络链接
		socket.close();
	}

	public static class CertTrustManager implements X509TrustManager
	{
		@Override
		public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException
		{
			checkServerTrusted(chain, authType);
		}

		@Override
		public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException
		{
			if(chain == null || chain.length == 0)
			{
				throw new CertificateException("No certificate fetched");
			}

			//	依次检查证书有效性，如果有问题会自动抛出异常
			for(X509Certificate cert : chain)
			{
				cert.checkValidity();
				//TODO	检查证书是否被吊销
			}

			//	打印证书信息
			for(int i = 0; i < chain.length; i ++)
			{
				System.out.println(">>>  No." + i + " of Certificate Ring  <<<");
				System.out.println(chain[i].toString());
			}
		}

		@Override
		public X509Certificate[] getAcceptedIssuers()
		{
			return new X509Certificate[] {};
		}
	}
}
